package org.erepublik.company.scanner;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;

import org.cyberneko.html.parsers.DOMParser;
import org.erepublik.company.Configuration;
import org.erepublik.company.CountryData;
import org.erepublik.company.EAlliance;
import org.erepublik.company.ECountry;
import org.erepublik.company.service.InternetExchangeRateService;
import org.json.JSONArray;
import org.json.JSONException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class CountryDataScanner {

    InternetExchangeRateService currency = new InternetExchangeRateService();
    
    private HashMap<Object, CountryData> map = new HashMap<Object, CountryData>();
    
    public CountryDataScanner() throws Exception {
        ECountry[] countries = ECountry.values();
        for (ECountry eCountry : countries) {
            Thread.sleep(1000);
            map.put(eCountry, getCountryDataFromInternet(eCountry));
        }
        Collection<CountryData> values = map.values();
//        for (EAlliance alliance : EAlliance.values()) {
//            Thread.sleep(30000);
//            map.put(alliance, getAveragedData(filter(alliance, values) ) );
//        }
        map.put(null, getAveragedData(values));
    }
    


    private Collection<CountryData> filter(EAlliance alliance, Collection<CountryData> values) {
        
        ArrayList<CountryData> list = new ArrayList<CountryData>();
        for (CountryData countryData : values) {
            if (alliance == countryData.getCountry().getAlliance())
                list.add(countryData);
        }
        return list;
    }



    public HashMap<Object, CountryData> getMap() {
        return map;
    }
    
    
    private CountryData getAveragedData(Collection<CountryData> data) {
        
        int totalPopulation=0;
        double totalTreasureInGold=0;
        double totalTreasureInCurrency=0;
        double averageExchangeRate=0;
        double averageExchangeRate2=0;
        int onlineCitizens=0;
        int newCitizens=0;
        
        for (CountryData countryData : data) {
            totalPopulation += countryData.getPopulation();
            totalTreasureInGold += countryData.getGoldTreasury();
            totalTreasureInCurrency += countryData.getCurrencyTreasury();
            averageExchangeRate += countryData.getPopulation() * countryData.getCurrencyForGold();
            averageExchangeRate2 += countryData.getPopulation() * countryData.getGoldForCurrency();
            onlineCitizens += countryData.getOnline();
            newCitizens += countryData.getNewCitizens();
        }
        averageExchangeRate /= totalPopulation;
        averageExchangeRate2 /= totalPopulation;
        
        CountryData countryData = new CountryData();
        countryData.setCurrencyForGold(averageExchangeRate);
        countryData.setGoldForCurrency(averageExchangeRate2);    
        countryData.setPopulation(totalPopulation);
        countryData.setGoldTreasury(totalTreasureInGold);
        countryData.setCurrencyTreasury(totalTreasureInCurrency);
        countryData.setOnline(onlineCitizens);
        countryData.setNewCitizens(newCitizens);
        
        return countryData;
    }





    public CountryData getCountryDataFromInternet(ECountry country) throws Exception {
        System.out.println("odczytuje o kraju z "+country);
        String url = "http://www.erepublik.com/en/country/economy/" + country.getUrlName();
        DOMParser parser = new DOMParser();
        parser.parse(url);
        Document page = parser.getDocument();
        Node treasureDiv = getTreasureDiv(page);
        double treasureInGold = getGoldTreasure(treasureDiv);
        double treasureInCurrency = getCurrencyTreasure(treasureDiv);
        CountryData countryData = new CountryData();
        countryData.setCountry(country);
        countryData.setGoldTreasury(treasureInGold);
        countryData.setCurrencyTreasury(treasureInCurrency);

        
        url = "http://www.erepublik.com/en/country/society/" + country.getUrlName();
        parser = new DOMParser();
        parser.parse(url);
        page = parser.getDocument();
        
        Node totalCitizensNode = getTotalCitizentNode(page);
        Node citizensNewTRep = totalCitizensNode.getParentNode().getNextSibling().getNextSibling();
        Node citizensNewTeD = citizensNewTRep.getFirstChild().getNextSibling()
                .getNextSibling().getNextSibling().getNextSibling().getNextSibling();
        int newCitizens = Integer.parseInt( citizensNewTeD.getFirstChild().getFirstChild().getNodeValue().toString() );
        
        Node citizensOnlineTRep = citizensNewTRep.getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling();
        Node citizensOnlineTeD = citizensOnlineTRep.getFirstChild().getNextSibling()
                .getNextSibling().getNextSibling().getNextSibling().getNextSibling();       
        int onlineCitizens = Integer.parseInt( citizensOnlineTeD.getFirstChild().getFirstChild().getNodeValue().toString() );
        
        countryData.setPopulation( Integer.parseInt( totalCitizensNode.getFirstChild().getFirstChild().getNodeValue() ) );
        countryData.setOnline(onlineCitizens);
        countryData.setNewCitizens(newCitizens);
        
        
        double kurs = currency.getExchangeRates().get(country);
        double kurs2 = currency.getExchangeRatesReverted().get(country);
        countryData.setGoldForCurrency(kurs);
        countryData.setCurrencyForGold(kurs2);
  
        
        
        return countryData;
    }
    
    
    
    
    
    
    private Node getTotalCitizentNode(Node page) {
        Node node = page.getFirstChild();

        while (node != null) {

            if ( node != null &&  "Total citizens".equals(node.getNodeValue()) )
                return node.getParentNode().getParentNode().getNextSibling().getNextSibling();
            Node child = getTotalCitizentNode(node);

            if (child != null)
                return child;
            node = node.getNextSibling();
        }

        return null;
    }






    private double getCurrencyTreasure(Node div) {


        double currency=0.0;
        Node currencyInteger = div.getFirstChild().getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling()
                    .getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling().getNextSibling();
        currency = Integer.parseInt(currencyInteger.getFirstChild().getNodeValue()) ;
        Node currencyReszta = currencyInteger.getNextSibling().getNextSibling();
        currency += Double.parseDouble(currencyReszta.getFirstChild().getNodeValue()) ;
        
        return currency;
    }






    private double getGoldTreasure(Node div) {
        double gold=0.0;
        Node goldInteger = div.getFirstChild().getNextSibling();
        gold = Integer.parseInt(goldInteger.getFirstChild().getNodeValue()) ;
        Node goldReszta = goldInteger.getNextSibling().getNextSibling();
        gold += Double.parseDouble(goldReszta.getFirstChild().getNodeValue()) ;
        
        return gold;
    }






    // zwraca czesc drzewa DOM, reprezentujacego tabele z podatkami
    private Node getTreasureDiv(Node page) {
        Node node = page.getFirstChild();

        while (node != null) {

            if (node.getNodeName().equals("DIV") && containsAttribute(node))
                return node;
            Node child = getTreasureDiv(node);

            if (child != null)
                return child;
            node = node.getNextSibling();
        }

        return null;
    }
    private boolean containsAttribute(Node node) {
        return node.getAttributes().getNamedItem("class") != null
                && node.getAttributes().getNamedItem("class").getNodeValue().equals("accountdisplay largepadded");
    }
    
    
    public void saveToJSONFile() {
        try {
            String urlToDirectory = Configuration.databasePath + "/country/";
            System.out.println(urlToDirectory + new Date().getTime() + "-country.json");
            File file = new File(urlToDirectory + new Date().getTime() + "-country.json");
            file.createNewFile();
            BufferedWriter out = null;

            out = new BufferedWriter(new FileWriter(file.getAbsolutePath()));

            JSONArray json = new JSONArray();
            Collection<CountryData> countries = map.values();
            for (CountryData country : countries) {
                try {
                    json.put(country.toJSONObject());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            out.write(json.toString());
            out.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws Exception {
        CountryDataScanner scanner = new CountryDataScanner();
        scanner.getMap();
        scanner.saveToJSONFile();
    }
    
}
